package com.elitel.frame.base.service.impl;

import com.elitel.common.utils.StringUtils;
import com.elitel.common.utils.SysUserUtils;
import com.elitel.common.utils.UUIDUtil;
import com.elitel.frame.base.service.SysPrjServiceService;
import com.elitel.frame.base.service.SysPrjserviceCategoryService;
import com.elitel.frame.main.dao.SysPrjserviceCategoryDao;
import com.elitel.frame.main.dao.SysPrjserviceCategoryRelDao;
import com.elitel.frame.main.dao.ext.ExtSysPrjserviceMapper;
import com.elitel.frame.main.dao.ext.RTree;
import com.elitel.frame.main.entity.SysPrjserviceCategory;
import com.elitel.frame.main.entity.SysPrjserviceCategoryRel;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据服务分类(SysPrjserviceCategory)表服务实现类
 *
 * @author makejava
 * @since 2025-01-08 17:03:05
 */
@Service("sysPrjserviceCategoryService")
public class SysPrjserviceCategoryServiceImpl implements SysPrjserviceCategoryService {
    @Resource
    private SysPrjserviceCategoryDao sysPrjserviceCategoryDao;
    @Resource
    private SysPrjserviceCategoryRelDao relDao;
    @Resource
    private SysPrjServiceService sysPrjServiceService;
    @Resource
    private ExtSysPrjserviceMapper extSysPrjserviceMapper;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public SysPrjserviceCategory queryById(String id) {
        return this.sysPrjserviceCategoryDao.queryById(id);
    }


    /**
     * 新增数据
     *
     * @param sysPrjserviceCategory 实例对象
     * @return 实例对象
     */
    @Override
    public SysPrjserviceCategory insert(SysPrjserviceCategory sysPrjserviceCategory) {
        this.sysPrjserviceCategoryDao.insert(sysPrjserviceCategory);
        return sysPrjserviceCategory;
    }

    /**
     * 修改数据
     *
     * @param sysPrjserviceCategory 实例对象
     * @return 实例对象
     */
    @Override
    public SysPrjserviceCategory update(SysPrjserviceCategory sysPrjserviceCategory) {
        this.sysPrjserviceCategoryDao.update(sysPrjserviceCategory);
        return this.queryById(sysPrjserviceCategory.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(String id) {
        return this.sysPrjserviceCategoryDao.deleteById(id) > 0;
    }


    public Object getGroupTree2() {
        Map<String, List<TreeNode>> map = new HashMap<>();
        //all
        List<RTree> list = extSysPrjserviceMapper.getAll2();
        List<RTree> db = extSysPrjserviceMapper.getDB2();
        List<RTree> simServer = extSysPrjserviceMapper.getByType2("simServer");
        List<RTree> polymerServer = extSysPrjserviceMapper.getByType2("polymerServer");
        List<RTree> fileServer = extSysPrjserviceMapper.getByType2("fileServer");
        List<TreeNode> all = buildTree3(list);
        List<TreeNode> dbSearch = buildTree3(db);
        List<TreeNode> simSearch = buildSim(simServer);
        List<TreeNode> polymerSearch = buildSim(polymerServer);
        List<TreeNode> fileSearch = buildSim(fileServer);
        dealAll(all);
        dealDBSearch(dbSearch);
        dealSim(simSearch);
        dealSim(polymerSearch);
        dealSim(fileSearch);
        sortAll(all);
        map.put("all", all.stream().sorted(Comparator.comparing(TreeNode::getOrder)).collect(Collectors.toList()));
        map.put("dbSrz", dbSearch.stream().sorted(Comparator.comparingInt(e -> e.getPath().length())).collect(Collectors.toList()));
        map.put("sim", simSearch.stream().sorted(Comparator.comparingInt(e -> e.getPath().length())).collect(Collectors.toList()));
        map.put("aggre", polymerSearch.stream().sorted(Comparator.comparingInt(e -> e.getPath().length())).collect(Collectors.toList()));
        map.put("file", fileSearch.stream().sorted(Comparator.comparingInt(e -> e.getPath().length())).collect(Collectors.toList()));
        return map;
    }

    private static void dealSim(List<TreeNode> all) {
        for (TreeNode treeNode : all) {
            if (!treeNode.getCode().equals("0")) treeNode.setGroupId(treeNode.getCode());
            for (TreeNode childChildChild : treeNode.getChildren()) {
                childChildChild.setGroupId(treeNode.getCode());
                childChildChild.setDataType(childChildChild.getCode());
            }
        }
    }

    private static void dealDBSearch(List<TreeNode> all) {
        for (TreeNode child : all) {
            String pcode = child.getCode();
            if (pcode.equals("0")) pcode = null;
            child.setDbKey(pcode);
            for (TreeNode childChild : child.getChildren()) {
                childChild.setDbKey(pcode);
                childChild.setServType(childChild.getCode());
                for (TreeNode childChildChild : childChild.getChildren()) {
                    childChildChild.setDbKey(pcode);
                    childChildChild.setServType(childChild.getCode());
                    childChildChild.setDataType(childChildChild.getCode());
                }
            }
        }
    }

    private static void sortAll(List<TreeNode> all) {
        for (TreeNode treeNode : all) {
            if (treeNode.getChildren() != null) {
                treeNode.setChildren(treeNode.getChildren().stream().sorted(Comparator.comparing(TreeNode::getOrder)).collect(Collectors.toList()));
                sortAll(treeNode.getChildren());
            }
        }
    }

    private static void dealAll(List<TreeNode> all) {
        for (TreeNode treeNode : all) {
            String code = treeNode.getCode();
            if (!code.equals("0")) treeNode.setGroupId(code);
            for (TreeNode gen1 : treeNode.getChildren()) {
                gen1.setGroupId(code);
                if (gen1.getCode().contains("simServer")) {
                    gen1.setServType("simServer");
                    for (TreeNode gen2 : gen1.getChildren()) {
                        gen2.setGroupId(code);
                        gen2.setServType("simServer");
                        gen2.setDataType(gen2.getCode());
                    }
                } else {
                    gen1.setDbKey(gen1.getCode());
                    for (TreeNode gen2 : gen1.getChildren()) {
                        gen2.setGroupId(code);
                        gen2.setDbKey(gen1.getCode());
                        gen2.setServType(gen2.getCode());
                        for (TreeNode gen3 : gen2.getChildren()) {
                            gen3.setGroupId(code);
                            gen3.setDbKey(gen1.getCode());
                            gen3.setServType(gen2.getCode());
                            gen3.setDataType(gen3.getCode());
                        }
                    }
                }
            }
        }
    }

    public static List<TreeNode> buildSim(List<RTree> pathList) {
        Map<String, TreeNode> nodeMap = new HashMap<>();
        List<TreeNode> rootNodes = new ArrayList<>();
        // 第一步：创建所有节点并存入Map
        for (RTree rTree : pathList) {
            String path = rTree.getParent() + "/" + rTree.getCode();
            path = path.replace("//", "/");
            TreeNode node = new TreeNode(path);
            node.setCode(rTree.getCode());
            node.setCnt(rTree.getCnt());
            node.setName(rTree.getName());
            nodeMap.put(path, node);
        }

        // 第二步：建立父子关系
        List<TreeNode> collect = nodeMap.values().stream().sorted(Comparator.comparing(e -> e.getParentPath().length())).collect(Collectors.toList());
        for (TreeNode node : collect) {
            String parentPath = node.getParentPath();
            if (parentPath.isEmpty() || !nodeMap.containsKey(parentPath)) {
                boolean add = true;
                for (String key : nodeMap.keySet()) {
                    if (parentPath.contains(key)) {
                        TreeNode parentNode = nodeMap.get(key);
                        parentNode.getChildren().add(node);
                        add = false;
                    }
                }
                // 无父节点，作为根节点
                if (add) rootNodes.add(node);
            } else {
                // 挂载到父节点的子节点列表
                TreeNode parentNode = nodeMap.get(parentPath);
                parentNode.getChildren().add(node);
            }
        }
        return rootNodes;
    }

    public static List<TreeNode> buildTree3(List<RTree> pathList) {
        Map<String, TreeNode> nodeMap = new HashMap<>();
        List<TreeNode> rootNodes = new ArrayList<>();
        // 第一步：创建所有节点并存入Map
        for (RTree rTree : pathList) {
            if (rTree.getParent() == null || rTree.getParent().contains("//")) continue;
            String path = rTree.getParent() + "/" + rTree.getCode();
            if (path.startsWith("//"))path = path.substring(1);
            TreeNode node = new TreeNode(path);
            node.setCode(rTree.getCode());
            node.setCnt(rTree.getCnt());
            node.setName(rTree.getName());
            node.setOrder(rTree.getOrder1());
            nodeMap.put(path, node);
        }
        Collection<TreeNode> collect = nodeMap.values();
        // 第二步：建立父子关系
        for (TreeNode node : collect) {
            String parentPath = node.getParentPath();
            if (parentPath.isEmpty() || !nodeMap.containsKey(parentPath)) {
                // 无父节点，作为根节点
                rootNodes.add(node);
            } else {
                // 挂载到父节点的子节点列表
                TreeNode parentNode = nodeMap.get(parentPath);
                parentNode.getChildren().add(node);
            }
        }
        return rootNodes;
    }

    /**
     * 获取树形结构
     *
     * @return
     */
    @Override
    public List<SysPrjserviceCategory> getTree() {
        LinkedList<SysPrjserviceCategory> resList = sysPrjserviceCategoryDao.selectAllList();
        for (SysPrjserviceCategory sysPrjserviceCategory : resList) {
            sysPrjserviceCategory.setCnt(this.setItem(sysPrjserviceCategory));
        }
        this.delNullNode(resList);
        SysPrjserviceCategory sysPrjserviceCategory = new SysPrjserviceCategory();
        sysPrjserviceCategory.setId("1");
        sysPrjserviceCategory.setCode("");
        sysPrjserviceCategory.setName("全部");
        sysPrjserviceCategory.setPid("0");
        Long allCnt = this.extSysPrjserviceMapper.getProjectServiceCount(null);
        sysPrjserviceCategory.setCnt(allCnt == null ? 0 : allCnt.intValue());
        resList.push(sysPrjserviceCategory);
        return resList;
    }

    int setItem(SysPrjserviceCategory item) {
        item.setId(UUIDUtil.randomUUID());
        item.setCreatedTime(new Date());
        item.setCreatedUser(SysUserUtils.getLoginAccount());
        item.setUpdatedTime(new Date());
        item.setUpdatedUser(SysUserUtils.getLoginAccount());
        if (CollectionUtils.isNotEmpty(item.getChildren())) {
            int cnt = 0;
            for (SysPrjserviceCategory child : item.getChildren()) {
                cnt += this.setItem(child);
            }
            item.setCnt(cnt);
            return cnt;
        } else {
            return item.getCnt();
        }
    }


    // 遍历树
    private void delNullNode(List<SysPrjserviceCategory> list) {
        for (SysPrjserviceCategory sysPrjserviceCategory : list) {
            List<SysPrjserviceCategory> children = sysPrjserviceCategory.getChildren();
            if (CollectionUtils.isNotEmpty(children)) {
                children.removeIf(child -> StringUtils.isEmpty(child.getName()));
                if (CollectionUtils.isNotEmpty(children)) {
                    delNullNode(children);
                }
            }
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveNode(SysPrjserviceCategory sysPrjserviceCategory) {
        String id = sysPrjserviceCategory.getId();
        String code = sysPrjserviceCategory.getCode();
        List<SysPrjserviceCategory> dbDataList = this.sysPrjserviceCategoryDao.queryByCode(code);
        if (dbDataList.size() > 1) {
            throw new RuntimeException("编码重复");
        }
        sysPrjserviceCategory.setUpdatedTime(new Date());
        sysPrjserviceCategory.setUpdatedUser(SysUserUtils.getLoginAccount());
        if (CollectionUtils.isEmpty(dbDataList)) {
            sysPrjserviceCategory.setId(UUIDUtil.randomUUID());
            sysPrjserviceCategory.setCreatedTime(new Date());
            sysPrjserviceCategory.setCreatedUser(SysUserUtils.getLoginAccount());
            this.sysPrjserviceCategoryDao.insert(sysPrjserviceCategory);
        } else {
            if (!id.equals(dbDataList.get(0).getId())) {
                throw new RuntimeException("编码重复");
            }
            this.sysPrjserviceCategoryDao.update(sysPrjserviceCategory);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delNode(SysPrjserviceCategory sysPrjserviceCategory) {
        String id = sysPrjserviceCategory.getId();
        // 先查询到子级及其更深层的节点
        List<SysPrjserviceCategory> children = this.sysPrjserviceCategoryDao.queryLowLevelNode(id);
        List<String> idList = children.stream().map(SysPrjserviceCategory::getId).collect(Collectors.toList());
        // 查询到关系数据
        if (CollectionUtils.isNotEmpty(idList)) {
            List<SysPrjserviceCategoryRel> relList = relDao.selectByCatIds(idList);
            ArrayList<String> serviceIds = new ArrayList<>();
            ArrayList<String> relIds = new ArrayList<>();
            for (SysPrjserviceCategoryRel sysPrjserviceCategoryRel : relList) {
                relIds.add(sysPrjserviceCategoryRel.getId());
                serviceIds.add(sysPrjserviceCategoryRel.getServiceId());
            }

            if (CollectionUtils.isNotEmpty(relIds)) {
                // 删除关系数据
                relDao.deleteByIds(relIds);
            }
            if (CollectionUtils.isNotEmpty(serviceIds)) {
                // 删除服务数据
                sysPrjServiceService.delByGuids(serviceIds);
            }
        }
        if (CollectionUtils.isNotEmpty(idList)) {
            // 删除节点数据
            sysPrjserviceCategoryDao.deleteByIds(idList);
        }


    }

    private List<SysPrjserviceCategory> buildTree(List<SysPrjserviceCategory> sysPrjserviceCategories) {
        List<SysPrjserviceCategory> res = new ArrayList<>();

        for (SysPrjserviceCategory sysPrjserviceCategory : sysPrjserviceCategories) {
            for (SysPrjserviceCategory node : sysPrjserviceCategories) {
                if (node.getPid().equals(sysPrjserviceCategory.getId())) {
                    List<SysPrjserviceCategory> children = sysPrjserviceCategory.getChildren();
                    if (children == null) {
                        children = new ArrayList<>();
                        children.add(node);
                    } else {
                        children.add(node);
                        children = children.stream().sorted(Comparator.comparing(SysPrjserviceCategory::getSort)).collect(Collectors.toList());
                    }
                    sysPrjserviceCategory.setChildren(children);
                }
            }
            if ("0".equals(sysPrjserviceCategory.getPid())) {
                res.add(sysPrjserviceCategory);
            }
        }
        return res.stream().sorted(Comparator.comparing(SysPrjserviceCategory::getSort)).collect(Collectors.toList());
    }
}
